package com.imooc.controller;

import com.google.gson.Gson;
import com.imooc.base.BaseInfoProperties;
import com.imooc.grace.result.GraceJSONResult;
import com.imooc.grace.result.ResponseStatusEnum;
import com.imooc.pojo.Users;
import com.imooc.pojo.vo.SaasUserVO;
import com.imooc.service.UsersService;
import com.imooc.utils.JWTUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * @author 啊昌
 * @date 2025/9/18 11:10
 * SaasPassportController saas端扫码登录
 */
@RestController
@Slf4j
@RequestMapping("saas")
public class SaasPassportController extends BaseInfoProperties {

//	 流程: 1. 生成二维码唯一qttoken令牌 2. 用户扫描二维码,根据qttoken令牌生成 预备二维码preToken
//	 3.执行二维码登录操作 携带preToken 进行校验
	@Autowired
	private JWTUtils jwtUtils;

	@Autowired
	private UsersService usersService;


	/**
	 * 获取二维码token
	 * 用于生成登录二维码的唯一标识token，并在redis中存储相关状态信息
	 *
	 * @return GraceJSONResult 包含生成的二维码token的响应结果
	 */
	@PostMapping("getQRToken")
	public GraceJSONResult getQRToken() {
		//1. 生成二维码的的QtToken
		String QRToken = UUID.randomUUID().toString();
		//2. redis 保存二维码的失效时间
		redis.set(SAAS_PLATFORM_LOGIN_TOKEN + ":" + QRToken, QRToken, 60 * 5); // 二维码的时间为五分钟
		//3. redis 保存二维码是否被扫描到
		redis.set(SAAS_PLATFORM_LOGIN_TOKEN_READ + ":" + QRToken, QRToken, 60 * 5);
		log.info("生成二维码的的token {}", QRToken);
		return GraceJSONResult.ok(QRToken);
	}

	/**
	 * 扫描二维码登录处理
	 * @param qrToken 二维码token
	 * @param httpRequest HTTP请求对象，用于获取请求头信息
	 * @return 返回预登录token或错误信息
	 */
	@PostMapping("scanCode")
	public GraceJSONResult scanCode(String qrToken, HttpServletRequest httpRequest) {
		//1. 校验二维码
		if (StringUtils.isBlank(qrToken)) {
			return GraceJSONResult.errorCustom(ResponseStatusEnum.FAILED);
		}
		// 从redis获取到二维码 和前端传递的二维码是否一致  校验QtToken的有效时间
		String redisQRToken = redis.get(SAAS_PLATFORM_LOGIN_TOKEN + ":" + qrToken);
		//equalsIgnoreCase  忽略大小写
		if (!redisQRToken.equalsIgnoreCase(qrToken)) {
			return GraceJSONResult.errorCustom(ResponseStatusEnum.FAILED);
		}

		// 验证用户身份信息
		String appUserIds = httpRequest.getHeader("appUserId");
		String appUserToken = httpRequest.getHeader("appUserToken");

		if (StringUtils.isBlank(appUserIds)|| StringUtils.isBlank(appUserToken)) {
			return GraceJSONResult.errorCustom(ResponseStatusEnum.FAILED);
		}

		String userJson = jwtUtils.checkJWT(appUserToken.split("@")[1]);

		if (StringUtils.isBlank(userJson) ) {
			return GraceJSONResult.errorCustom(ResponseStatusEnum.FAILED);
		}

		//1. 生成二维码的的预备 preToken
		String preToken = UUID.randomUUID().toString();
		redis.set(SAAS_PLATFORM_LOGIN_TOKEN + ":" + qrToken, preToken, 60 * 5); // 二维码的时间为五分钟
		//1 表示已被扫描
		redis.set(SAAS_PLATFORM_LOGIN_TOKEN_READ + ":" + qrToken, "1,"+preToken, 60 * 5);

		return GraceJSONResult.ok(preToken);
	}


	/**
	 * 处理二维码已被读取的请求
	 * @param qrToken 二维码令牌，用于标识特定的二维码会话
	 * @return GraceJSONResult 包含二维码读取状态信息的结果对象，成功时返回包含状态码和信息的列表，失败时返回自定义错误信息
	 */
	@PostMapping("codeHasBeenRead")
	public GraceJSONResult codeHasBeenRead(String qrToken) {
		//定时扫描二维码是否被扫描

		// 检查二维码令牌是否为空
		if(StringUtils.isBlank(qrToken)){
			return GraceJSONResult.errorCustom(ResponseStatusEnum.FAILED);
		}
		String readStr = redis.get(SAAS_PLATFORM_LOGIN_TOKEN_READ + ":" + qrToken);

		if (StringUtils.isBlank(readStr)) {
			return GraceJSONResult.errorCustom(ResponseStatusEnum.FAILED);
		}


		// 从Redis中获取二维码读取状态信息并解析
		List list = new ArrayList();
		String[] readArr = readStr.split(",");
		if (readArr.length >= 2) {
			list.add(Integer.valueOf(readArr[0]));
			list.add(readArr[1]);
		} else {
			list.add(0);
		}

		return GraceJSONResult.ok(list);
	}

	/**
	 * 执行二维码登录操作
	 * @param userId 用户ID
	 * @param qrToken 二维码令牌
	 * @param preToken 预登录令牌
	 * @return 登录结果，包含操作状态信息
	 */
	@PostMapping("goQRLogin")
	public GraceJSONResult goQRLogin(String userId,
	                                 String qrToken,
	                                 String preToken) {
		// 从Redis中获取预登录令牌信息
		String preTokenRedisArr = redis.get(SAAS_PLATFORM_LOGIN_TOKEN_READ + ":" + qrToken);
		if(StringUtils.isNoneBlank(preTokenRedisArr)){
			String preTokenRedis = preTokenRedisArr.split(",")[1]; //这个就是预登录的token
			if(StringUtils.isNoneBlank(preTokenRedis)){
				Users user = usersService.getById(userId);
				if(user == null ){
					return GraceJSONResult.errorCustom(ResponseStatusEnum.USER_NOT_EXIST_ERROR);
				}
				// 存入用户信息到redis中，因为H5在未登录的情况下，拿不到用户id，所以暂存用户信息到redis。
				// *如果使用websocket是可以直接通信H5获得用户id，则无此问题
				redis.set(REDIS_SAAS_USER_INFO + ":temp:" + preToken, new Gson().toJson(user), 5 * 60);
			}
		}
		return GraceJSONResult.ok();
	}


	/**
	 * 页面登录跳转
	 * @param preToken
	 * @return
	 */
	@PostMapping("checkLogin")
	public GraceJSONResult checkLogin(String preToken) {

		if (StringUtils.isBlank(preToken))
			return GraceJSONResult.ok("");

		// 获得用户临时信息
		String userJson = redis.get(REDIS_SAAS_USER_INFO + ":temp:" + preToken);

		if (StringUtils.isBlank(userJson))
			return GraceJSONResult.errorCustom(ResponseStatusEnum.USER_NOT_EXIST_ERROR);

		// 确认执行登录后，生成saas用户的token，并且长期有效
		String saasUserToken = jwtUtils.createJWTWithPrefix(userJson, TOKEN_SAAS_PREFIX);

		// 存入用户信息，长期有效
		redis.set(REDIS_SAAS_USER_INFO + ":" + saasUserToken, userJson);

		return GraceJSONResult.ok(saasUserToken);
	}

		/**
	 * 获取SaaS用户信息
	 * @param token 用户令牌，用于从Redis中获取用户信息
	 * @return GraceJSONResult 包含用户信息的JSON结果对象
	 */
	@GetMapping("info")
	public GraceJSONResult info(String token) {

		// 从Redis中获取用户信息JSON字符串
		String userJson = redis.get(REDIS_SAAS_USER_INFO + ":" + token);
		// 将JSON字符串转换为Users对象
		Users saasUser = new Gson().fromJson(userJson, Users.class);

		// 创建VO对象并复制属性
		SaasUserVO saasUserVO = new SaasUserVO();
		BeanUtils.copyProperties(saasUser, saasUserVO);

		// 返回包含用户信息的成功结果
		return GraceJSONResult.ok(saasUserVO);
	}


	/**
	 * 用户退出登录接口
	 * @param token 用户登录凭证
	 * @return 返回操作结果，包含状态码和消息
	 */
	@PostMapping("logout")
	public GraceJSONResult logout(String token) {
		return GraceJSONResult.ok();
	}



}
